//
//  XSVideRecordViewController.m
//  AudioVideo
//
//  Created by xueshan1 on 2019/8/23.
//  Copyright © 2019 xueshan1. All rights reserved.
//

#import "XSVideRecordViewController.h"
#import "XSShootingToolBar.h"

@interface XSVideRecordViewController ()<AVCaptureFileOutputRecordingDelegate,XSShootingToolBarDelegate>

@property(nonatomic,strong)AVCaptureSession *captureSession;
@property(nonatomic,strong)AVCaptureDevice *videoDevice;
@property(nonatomic,strong)AVCaptureDevice *audioDevice;
@property(nonatomic,strong)AVCaptureDeviceInput *videoInput;
@property(nonatomic,strong)AVCaptureDeviceInput *audioInput;
@property(nonatomic,strong)AVCaptureMovieFileOutput  *movieFileOutput;//视频输出流
@property(nonatomic, strong) AVCaptureStillImageOutput *imageOutPut;//照片输出流对象
@property(nonatomic,strong)AVCaptureVideoPreviewLayer *videoPreviewLayer;
@property(nonatomic,assign)UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@property(nonatomic,copy)NSString *tempRecordPath;

@property(nonatomic,strong)UIView *playView;
@property(nonatomic,strong)XSShootingToolBar *toolBar;
@property(nonatomic,strong)UIImageView *focusOnImg;

//拍照照片显示
@property (nonatomic, strong) UIImageView *takedImageView;
//拍照的照片
@property (nonatomic, strong) UIImage *takedImage;

@end

@implementation XSVideRecordViewController


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    [XSFileManager deletePath:self.tempRecordPath];
    [self initSession];
    
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    if (![self.captureSession isRunning]) {
        [self.captureSession startRunning];
    }

    [self.toolBar buttonAnimation:NO];

    self.takedImageView.hidden = YES;

}
- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    
    [self stopRecording];
    
     [[XSAVPlayer shareInstance]sf_deallocPlayer];
    self.takedImage = nil;
    
}
- (void)setupUI{
    XSShootingToolBar *bar = [[XSShootingToolBar alloc]initWithFrame:CGRectMake(0, kHeight - 200, kWidth, 200)];
    bar.toolBarDelegate = self;
    [self.view addSubview:bar];
    self.toolBar = bar;
    
    UIButton *btnSwitch = [[UIButton alloc] init];
    btnSwitch.frame = CGRectMake(kWidth - 100, 44, 80, 30);
    [btnSwitch setImage:[UIImage imageNamed:@"btn_video_flip_camera"] forState:UIControlStateNormal];
    [btnSwitch addTarget:self action:@selector(switchCameraBackOrFront:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btnSwitch];
    
    //设置聚焦点图片
    UIImageView *focusOnImg = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"icon_focusing"]];
    focusOnImg.transform = CGAffineTransformIdentity;
    focusOnImg.alpha = 0;
    [self.view addSubview:focusOnImg];
    self.focusOnImg = focusOnImg;
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapScreen:)];
    [self.view addGestureRecognizer:tap];
    
}
- (void)initSession{
    _captureSession = [[AVCaptureSession alloc]init];
    //分辨率
    if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
        [_captureSession setSessionPreset:AVCaptureSessionPreset1280x720];
    }
    //输入设备
//    _videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    _videoDevice = [self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];
    _audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    
    NSError *error=nil;
    _videoInput = [[AVCaptureDeviceInput alloc]initWithDevice:_videoDevice error:&error];
    if (error) {
        NSLog(@"取得设备输入对象时出错，错误原因：%@",error.localizedDescription);
        return;
    }
    _audioInput = [[AVCaptureDeviceInput alloc]initWithDevice:_audioDevice error:&error];
    if (error) {
        NSLog(@"取得设备输入对象时出错，错误原因：%@",error.localizedDescription);
        return;
    }
    //添加到会话
    if ([_captureSession canAddInput:_videoInput]) {
        [_captureSession addInput:_videoInput];
    }
    if ([_captureSession canAddInput:_audioInput]) {
        [_captureSession addInput:_audioInput];
    }
    
    _movieFileOutput = [[AVCaptureMovieFileOutput alloc]init];
    if ([_captureSession canAddOutput:_movieFileOutput]) {
        [_captureSession addOutput:_movieFileOutput];
    }
    //此处是为了设置视频防抖动
    AVCaptureConnection *captureConnection = [_movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    if ([captureConnection isVideoStabilizationSupported]) {
        captureConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
    
//------
    self.imageOutPut = [[AVCaptureStillImageOutput alloc]init];
    //这是输出流的设置参数AVVideoCodecJPEG参数表示以JPEG的图片格式输出图片
    NSDictionary *dicOutputSetting = [NSDictionary dictionaryWithObject:AVVideoCodecJPEG forKey:AVVideoCodecKey];
    [self.imageOutPut setOutputSettings:dicOutputSetting];
    //将输出流添加到session
    if ([_captureSession canAddOutput:self.imageOutPut]) {
        [_captureSession addOutput:self.imageOutPut];
    }
    
    
    
    //预览层
    _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession];
    _videoPreviewLayer.frame = CGRectMake(0, 0, kWidth, kHeight);
    _videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
     [self.view.layer insertSublayer:_videoPreviewLayer below:self.toolBar.layer];
    [self.view.layer setMasksToBounds:YES];

}

- (void)startRecording{
    self.tempRecordPath = [XSFileManager tempVideoPath];
    if (![self.movieFileOutput isRecording]) {
        if (![self.captureSession isRunning]) {
            [self.captureSession startRunning];
        }
        //支持多任务
        if ([UIDevice currentDevice].isMultitaskingSupported) {
            self.backgroundTaskIdentifier = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:nil];
        }
        //预览层和视频方向保持一致
        AVCaptureConnection *connection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
        connection.videoOrientation = [self.videoPreviewLayer connection].videoOrientation;
        [self.movieFileOutput startRecordingToOutputFileURL:[NSURL fileURLWithPath:self.tempRecordPath] recordingDelegate:self];
        
    }else{
        [self.movieFileOutput stopRecording];
    }
    
}
- (void)stopRecording{
    if ([self.movieFileOutput isRecording]) {
        [self.movieFileOutput stopRecording];
    }
    if ([self.captureSession isRunning]) {
        [self.captureSession stopRunning];
    }
}

#pragma mark - record delegate
- (void)captureOutput:(AVCaptureFileOutput *)output didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray<AVCaptureConnection *> *)connections{
    NSLog(@"开始录制");

}
- (void)captureOutput:(AVCaptureFileOutput *)output didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray<AVCaptureConnection *> *)connections error:(nullable NSError *)error{
    NSLog(@"完成录制");
    
    [self playRecordVideo];

}

- (UIView *)playView{
    if (!_playView) {
        _playView = [[UIView alloc]initWithFrame:self.view.bounds];
        _playView.backgroundColor = [UIColor clearColor];
        [self.view insertSubview:_playView belowSubview:self.toolBar];
    }
    return _playView;
}
- (void)playRecordVideo{
    self.playView.hidden = NO;
    [XSAVPlayer shareInstance].isRecyclePlay = YES;
    [[XSAVPlayer shareInstance]playVideoWithURLString:self.tempRecordPath onPlayView:self.playView isLocalFile:YES];
    
}
- (void)stopPlayRecordVideo{
    if ([XSAVPlayer shareInstance].playState == XSAVPlayerState_Playing) {
        [[XSAVPlayer shareInstance]sf_audioPause];
    }
    
    self.playView.hidden = YES;
    
    if (![self.captureSession isRunning]) {
        [self.captureSession startRunning];
    }
}

#pragma mark - bar delegate

- (void)shootingToolBarClosed:(XSShootingToolBar *)toolBar{
    [self stopPlayRecordVideo];
    [self.navigationController popViewControllerAnimated:YES];
}
- (void)shootingToolBarEditCancled:(XSShootingToolBar *)toolBar{
    [self stopPlayRecordVideo];
    [XSFileManager deletePath:self.tempRecordPath];
    
    self.takedImageView.hidden = YES;
    self.takedImage = nil;
    [self setFocusAtPoint:self.view.center];
    
}
//中间 圆
- (void)shootingToolBarEditClicked:(XSShootingToolBar *)toolBar{
//    [self stopPlayRecordVideo];
//    //->编辑页面
//
//    XSVideoEditeViewController *vc = [XSVideoEditeViewController new];
//    vc.videoURL = [NSURL fileURLWithPath:self.tempRecordPath];
//    [self.navigationController pushViewController:vc animated:NO];

    
}
- (void)shootingToolBarEditSure:(XSShootingToolBar *)toolBar{
    if (self.takedImage) {
        [XSPhotosManager saveImageToAblum:self.takedImage completion:^(BOOL success, PHAsset *asset) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [toolBar buttonAnimation:NO];
                XSImageEditViewController *imageVC = [XSImageEditViewController new];
                imageVC.photo = self.takedImage;
                [self.navigationController pushViewController:imageVC animated:YES];
                
            });
 
        }];
        
        
    }else if (IS_NSString(self.tempRecordPath)){
        [self stopPlayRecordVideo];
        
        [XSPhotosManager saveToPhotoLibrary:[NSURL fileURLWithPath:self.tempRecordPath] completion:^(NSError * _Nonnull error){
            dispatch_async(dispatch_get_main_queue(), ^{
                [toolBar buttonAnimation:NO];
                //->编辑页面
                XSVideoEditeViewController *vc = [XSVideoEditeViewController new];
                vc.videoURL = [NSURL fileURLWithPath:self.tempRecordPath];
                [self.navigationController pushViewController:vc animated:YES];
            });
         
        }];
        
    }
   
    
}
- (void)shootingToolBarStartRecording:(XSShootingToolBar *)toolBar{
    [self stopPlayRecordVideo];
    [self startRecording];
    
}
- (void)shootingToolBar:(XSShootingToolBar *)toolBar endRecordProgress:(CGFloat)progress{
    [self stopRecording];
    
}
- (void)singleTapShootBtn:(XSShootingToolBar *)toolBar{
    
    AVCaptureConnection * videoConnection = [self.imageOutPut connectionWithMediaType:AVMediaTypeVideo];
    videoConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
    if (!videoConnection) {
        NSLog(@"take photo failed!");
        return;
    }
    
    if (!_takedImageView) {
        _takedImageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
        _takedImageView.backgroundColor = [UIColor blackColor];
        _takedImageView.hidden = YES;
        _takedImageView.contentMode = UIViewContentModeScaleAspectFit;
        [self.view insertSubview:_takedImageView belowSubview:self.toolBar];
    }
    __weak typeof(self) weakSelf = self;
    [self.imageOutPut captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        if (imageDataSampleBuffer == NULL) {
            return;
        }
        NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage * image = [UIImage imageWithData:imageData];
        weakSelf.takedImage = image;
        weakSelf.takedImageView.hidden = NO;
        weakSelf.takedImageView.image = image;
        [weakSelf.captureSession stopRunning];
    }];
    
}

#pragma mark - action

- (void)switchCameraBackOrFront:(UIButton *)btn{
    AVCaptureDevice *currentDevice = [self.videoInput device];
    AVCaptureDevicePosition curPosition = [currentDevice position];
    if (curPosition == AVCaptureDevicePositionBack) {
        curPosition = AVCaptureDevicePositionFront;
    }else{
        curPosition = AVCaptureDevicePositionBack;
    }
    AVCaptureDevice *toDevice = [self getCameraDeviceWithPosition:curPosition];
    //重新配置
    AVCaptureDeviceInput *toDeviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:toDevice error:nil];
    
    [self.captureSession beginConfiguration];

    [self.captureSession removeInput:self.videoInput];
    if ([self.captureSession canAddInput:toDeviceInput]) {
        [self.captureSession addInput:toDeviceInput];
        self.videoInput = toDeviceInput;
    }
    [self.captureSession commitConfiguration];
    
}

- (void)tapScreen:(UITapGestureRecognizer *)tap{
    CGPoint point = [tap locationInView:self.view];
    if (point.y > kHeight - 150) {
        return;
    }
    self.focusOnImg.transform = CGAffineTransformIdentity;
    self.focusOnImg.center = point;
    self.focusOnImg.transform = CGAffineTransformMakeScale(2, 2);
    self.focusOnImg.alpha = 1.0;
    [UIView animateWithDuration: 0.6 animations:^{
        self.focusOnImg.transform = CGAffineTransformIdentity;
    } completion:^(BOOL finished) {
        self.focusOnImg.alpha = 0;
    }];
    
    [self setFocusAtPoint:point];
}

- (void)setFocusAtPoint:(CGPoint)point{
    CGPoint cameraPoint = [self.videoPreviewLayer captureDevicePointOfInterestForPoint:point];
    
    AVCaptureDevice *devide = self.videoDevice;
    if ([devide lockForConfiguration:nil]) {
        
        if ([devide isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
            [devide setFocusMode:AVCaptureFocusModeAutoFocus];
        }
        if ([devide isFocusPointOfInterestSupported]) {
            [devide setFocusPointOfInterest:cameraPoint];
        }
        if ([devide isExposureModeSupported:AVCaptureExposureModeAutoExpose]) {
            [devide setExposureMode:AVCaptureExposureModeAutoExpose];
        }
        if ([devide isExposurePointOfInterestSupported]) {
            [devide setExposurePointOfInterest:cameraPoint];
        }
        
        [devide unlockForConfiguration];
    }

}

- (AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position {
    AVCaptureDeviceDiscoverySession *session = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:position];
    //    NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];//ios10 之前
    for (AVCaptureDevice *camera in session.devices) {
        if ([camera position] == position) {
            return camera;
        }
    }
    return nil;
}


@end
